#pragma once
#include <memory>
#include <functional>

#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Log.hpp"
#include "Protocol.hpp"

using namespace socket_n;
using process_t = std::function<std::shared_ptr<Response>(std::shared_ptr<Request>)>;
class IoService
{
public:
    IoService(process_t process)
        : _process(process)
    {
    }
    void IoExecute(SockPtr sockPtr, InetAddr &addr)
    {
        std::string packageStream;
        std::shared_ptr<Request> req_ptr = std::make_shared<Request>();
        std::string recvMessage;
        std::string sendMessage;
        while (true)
        {
            // 读内容
            ssize_t n = sockPtr->Recv(recvMessage);
            // 数据读取出错或者没数据了，直接break，关闭套接字，停止对该客户端的服务
            // 客户端可以重新建立连接
            if (n <= 0)
            {
                LOG(ERROR, "read error or rend end: %s\n", addr.AddrStr().c_str());
                break;
            }
            packageStream += recvMessage;
            // 提取一个完整的报文
            std::string jsonStr = DeCode(packageStream);
            if (jsonStr == "")
                continue;
            // 反序列化
            req_ptr->Deserialize(jsonStr);
            // 计算
            auto res_ptr = _process(req_ptr);
            // 序列化
            res_ptr->Serialize(sendMessage);
            // 添加报头
            sendMessage = EnCode(sendMessage);
            // 向套接字中写
            sockPtr->Send(sendMessage);
        }
    }
    ~IoService()
    {
    }

private:
    process_t _process;
};